package Game.Items;

import java.lang.reflect.InvocationTargetException;
import java.util.*;

import org.newdawn.slick.SlickException;

import Game.Objects.*;

/** Inventory class 
 * @author Aikidos
 */
public class Inventory {
	
	/** List of game item */
	private List<GameItem> _lstItems = new ArrayList<GameItem>();
	
	/** List of drop chance */
	private Map<GameItem, Integer> _lstDropChance = new HashMap<GameItem, Integer>();
	
	/** Owner game object */
	private GameObject _gameObject;
	
	public Inventory(GameObject gameObject) {
		_gameObject = gameObject;
	}
	
	/** Returns owner game object
	 * @return Owner game object
	 */
	public GameObject getGameObject() {
		return _gameObject;
	}
	
	/** Returns list of item
	 * @return List of item
	 */
	public List<GameItem> getItems() {
		return _lstItems;
	}
	
	/** Returns drop chance of 
	 * @param gameItem - Game item
	 * @return Drop chance
	 */
	public int getDropChance(GameItem gameItem) {
		return _lstDropChance.get(gameItem);
	}
	
	/** Returns true if inventory is empty
	 * @return True if inventory is empty
	 */
	public boolean isEmpty() {
		return (_lstItems.size() == 0) ? true : false;
	}
	
	/** Add item to inventory
	 * @param gameItem - Game item
	 * @return Added game item
	 */
	public GameItem addItem(GameItem gameItem) {
		if (!gameItem.isStackable()) {
			gameItem.setOwnerGameObject(_gameObject);
			_lstItems.add(gameItem);

			// Add to drop chance list
			_lstDropChance.put(gameItem, 100);
		} else {
			for (GameItem item : _lstItems) {
				if (item.getClass().getName() == gameItem.getClass().getName()) {
					item.setNumOfItems(item.getNumOfItems() + 1);
					
					// Add weight
					if (_gameObject.isPlayer()) {
						((GOPlayer) _gameObject).addWeight(gameItem.getWeight());
					}
					
					return item;
				}
			}
			
			gameItem.setOwnerGameObject(_gameObject);
			_lstItems.add(gameItem);
			gameItem.setNumOfItems(1);

			// Add to drop chance list
			_lstDropChance.put(gameItem, 100);
		}
		
		// Add weight
		if (_gameObject.isPlayer()) {
			((GOPlayer) _gameObject).addWeight(gameItem.getWeight());
		}
		
		return gameItem;
	}
	
	/** Add item to inventory
	 * @param gameItem - Game item
	 * @param dropChance - Drop chance
	 * @return Added game item
	 */
	public GameItem addItem(GameItem gameItem, int dropChance) {
		if (!gameItem.isStackable()) {
			gameItem.setOwnerGameObject(_gameObject);
			_lstItems.add(gameItem);

			// Add to drop chance list
			_lstDropChance.put(gameItem, dropChance);
		} else {
			for (GameItem item : _lstItems) {
				if (item.getClass().getName() == gameItem.getClass().getName()) {
					item.setNumOfItems(item.getNumOfItems() + 1);
					
					// Add weight
					if (_gameObject.isPlayer()) {
						((GOPlayer) _gameObject).addWeight(gameItem.getWeight());
					}
					
					return item;
				}
			}
			
			gameItem.setOwnerGameObject(_gameObject);
			_lstItems.add(gameItem);
			gameItem.setNumOfItems(1);

			// Add to drop chance list
			_lstDropChance.put(gameItem, dropChance);
		}
		
		// Add weight
		if (_gameObject.isPlayer()) {
			((GOPlayer) _gameObject).addWeight(gameItem.getWeight());
		}
		
		return gameItem;
	}
	
	/** Delete item from inventory
	 * @param gameItem - Game item
	 * @param tryStackable - If true and game item is stackable then method delete only one item
	 */
	public void deleteItem(GameItem gameItem, boolean tryStackable) {
		if (!tryStackable) {
			if (_lstItems.contains(gameItem)) {
				if (gameItem.isOn()) gameItem.off();
				
				_lstItems.remove(gameItem);
				
				// Sub weight
				if (_gameObject.isPlayer()) {
					((GOPlayer) _gameObject).subWeight(gameItem.getWeight());
				}
			}
		} else {
			int numOfItems = gameItem.getNumOfItems() - 1;
			if (numOfItems <= 0) _lstItems.remove(gameItem);
			else gameItem.setNumOfItems(numOfItems);
			
			// Sub weight
			if (_gameObject.isPlayer()) {
				((GOPlayer) _gameObject).subWeight(gameItem.getWeight());
			}
		}
	}

	/** Use item (on/off if item is equip)
	 * @param gameItem - Game item
	 */
	public void useItem(GameItem gameItem) throws SlickException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, ClassNotFoundException {
		if (_lstItems.contains(gameItem))
		{
			// If item is not equip
			if (!gameItem.IsEquip)
			{
				// Use item and remove it after use
				if (gameItem.use()) {
					if (!gameItem.isStackable())
						{
							_lstItems.remove(gameItem);
							
							// Sub weight
							if (_gameObject.isPlayer()) {
								((GOPlayer) _gameObject).subWeight(gameItem.getWeight());
							}
						}
					else {
						int numOfItems = gameItem.getNumOfItems() - 1;
						if (numOfItems <= 0) _lstItems.remove(gameItem);
						else gameItem.setNumOfItems(numOfItems);
						
						// Sub weight
						if (_gameObject.isPlayer()) {
							((GOPlayer) _gameObject).subWeight(gameItem.getWeight());
						}
					}
				}
			}
			else
			{
				if (gameItem.isOn()) gameItem.off();
				else {
					gameItem.on();
					
					switch (gameItem.Category) {
					case Weapon:
						for (GameItem item : _lstItems) {
							if ((item != gameItem) && (item.Category == gameItem.Category))
								item.off();
						}
						break;
						
					case Helmet:
						for (GameItem item : _lstItems) {
							if ((item != gameItem) && (item.Category == gameItem.Category))
								item.off();
						}
						break;
						
					case Chestplate:
						for (GameItem item : _lstItems) {
							if ((item != gameItem) && (item.Category == gameItem.Category))
								item.off();
						}
						break;
						
					case Shield:
						for (GameItem item : _lstItems) {
							if ((item != gameItem) && (item.Category == gameItem.Category))
								item.off();
						}
						break;
						
					case Gloves:
						for (GameItem item : _lstItems) {
							if ((item != gameItem) && (item.Category == gameItem.Category))
								item.off();
						}
						break;
						
					case Boots:
						for (GameItem item : _lstItems) {
							if ((item != gameItem) && (item.Category == gameItem.Category))
								item.off();
						}
						break;
					}
					
				}
			}
		}
	}


}
